#pragma once
#include <iostream>
#include <string>
#include <memory>
#include "Socket.hpp"
// #include"Log.hpp"
#include "Epoller.hpp"

using namespace std;
using namespace Network;
using namespace EpollMoudle;

const static int gbacklog = 32;

string EventToString(uint32_t events)
{
    string info;
    if(events&EPOLLIN)info+="EPOLLIN ";
    if(events&EPOLLOUT)info+="EPOLLOUT ";
    if(events&EPOLLET)info+="EPOLLET";

    return info;
}


class EpollServer
{
    const static int gmaxevents = 64;

public:
    EpollServer(int port) : _port(port), _listensock(new TcpSocket()), _isrunning(false), _epoller(new Epoller())
    {
    }
    bool InitServer()
    {
        // 1.创建listensock
        _listensock->BuildlistenSocketMethod(_port, gbacklog);
        lg.LogMessage(Info, "init socket success ,listensock is %d \n", _listensock->GetSockfd());
        // 2.创建epoll模型
        _epoller->InitEpoller();
        lg.LogMessage(Info, "init epoller success\n");

        // 3.将listensock注册到epoll模型中
        _epoller->AddEvent(_listensock->GetSockfd(), EPOLLIN);
        return true;
    }
    bool Accepter(string *peerip, uint16_t *peerport)
    {
        // 监听事件就绪
        int sockfd = _listensock->AcceptConnection(peerip, peerport);
        if (sockfd < 0)
        {
            lg.LogMessage(Warning, "accept error...\n");
            return false;
        }
        // 获取连接成功了
        _epoller->AddEvent(sockfd, EPOLLIN); //
        return true;
    }
    int Recever(int sockfd,string* out)
    {
        char buffer[1024];
        int n=recv(sockfd,buffer,sizeof(buffer)-1,0);
        buffer[n]=0;
        if(n>0)
        {
            *out=buffer;
        }
        return n;
    }
    void HandlerEvent(int n)
    {
        lg.LogMessage(Debug, "%d 个 events 已经就绪了\n");
        for (int i = 0; i < n; i++)
        {
            lg.LogMessage(Debug, "ready fd :%d, Event is :%s\n", _revs[i].data.fd, EventToString(_revs[i].events).c_str());
            int sockfd = _revs[i].data.fd;
            uint32_t events = _revs[i].events;
            if (events & EPOLLIN)
            {
                // 读事件分为两种 //1.listen 2.普通IO
                if (sockfd == _listensock->GetSockfd())
                {
                    string clientip;
                    uint16_t clientport;
                    if(!Accepter(&clientip, &clientport))
                        continue;
                    lg.LogMessage(Info,"accept client success, client[%s:%d]\n",clientip.c_str(),clientport);
                }
                else
                {
                    string message;
                    int n=Recever(sockfd,&message);
                    if(n>0)
                    {
                       cout<<"client#  "<<message<<endl;

                        message.resize(message.size()-strlen("\r\n"));

                       //直接写
                       string echo_message="echo message: "+message;                       
                       send(sockfd,echo_message.c_str(),echo_message.size(),0);
                    }
                    else
                    {
                        if(n==0)
                        {
                            lg.LogMessage(Info,"client : %d close\n",sockfd);
                        }
                        else
                        {
                            lg.LogMessage(Info,"client recv: %d error\n",sockfd);
                        }
                        _epoller->DelEvent(sockfd);//epoll移除一个fd，这个fd必须是合法的fd，才能被正确移除
                        close(sockfd);
                    }
                    
                    
                }
            }
        }
    }
    void Loop()
    {
        _isrunning = true;
        while (_isrunning)
        {
            _epoller->DebugFdList();
            int timeout = 1000;
            int n = _epoller->Wait(_revs, gmaxevents, timeout);
            switch (n)
            {
            case 0:
                lg.LogMessage(Debug, "timeeout...\n");
                break;
            case -1:
                lg.LogMessage(Error, "epoll wait error...\n");
                break;
            default:
                // 事件就绪了
                lg.LogMessage(Info, "event happened...\n");
                HandlerEvent(n);
                break;
            }
        }
        _isrunning = false;
    }
    ~EpollServer() {}

private:
    unique_ptr<Socket> _listensock;
    unique_ptr<Epoller> _epoller;
    uint16_t _port;
    bool _isrunning;

    struct epoll_event _revs[gmaxevents];
};